package zerous.dodgestones.screen;

import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.math.*;
import com.badlogic.gdx.scenes.scene2d.*;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.*;
import com.badlogic.gdx.utils.*;
import zerous.dodgestones.*;
import zerous.dodgestones.core.*;

public final class GameScreen extends ScreenAdapter   
{
	boolean usageOpen, scoreCounting;
	BitmapFont font;
	SpriteBatch batch;
	SpriteBatch batch2;
	public OrthographicCamera camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
	public Stage stage;
	
	Sprite usage;

	Array<Stone> stones = new Array<Stone>();

	Pool<Stone> stonePool = new Pool<Stone>() {
		@Override
		protected Stone newObject() {
			return new Stone();
		}
	};
	
	Array<Star> stars = new Array<Star>();
	Pool<Star> starPool = new Pool<Star>() {

		@Override
		protected Star newObject() {
			// TODO: Implement this method
			return new Star();
		}
	};
	
	int score = 0;

	Button btn, mainMenu;
	Player player;

	int timer;
	
	Traveler game;

	public GameScreen(Traveler game) {
		this.game = game;
	}

	@Override
	public void show() {
		// TODO: Implement this method
		super.show();
		scoreCounting = false;
		usageOpen = true;
		font = new BitmapFont();
		font.setColor(Color.WHITE);
		font.setScale(10);
		batch = new SpriteBatch();
		batch2 = new SpriteBatch();
		stage = new Stage();
		player = new Player();
		usage = new Sprite(Traveler.USAGE);
		usage.setSize(usage.getWidth()*Info.PIXEL_SIZE,usage.getHeight()*Info.PIXEL_SIZE);
		usage.setPosition(Gdx.graphics.getWidth() - usage.getWidth(), 0);
		
		
		setupButtons();
		
		Gdx.input.setInputProcessor(stage);
		player.position.set(-20, stage.getCamera().viewportHeight / 2);
	}
	
	private void setupButtons() {
		Sprite t = new Sprite(Traveler.RESTART);
		Sprite tt = new Sprite(Traveler.BACK);
		tt.setSize(tt.getWidth()*Info.PIXEL_SIZE, tt.getHeight()*Info.PIXEL_SIZE);
		t.setSize(t.getWidth()*Info.PIXEL_SIZE, t.getHeight()*Info.PIXEL_SIZE);
		btn = new Button(new SpriteDrawable(t));
		mainMenu = new Button(new SpriteDrawable(tt));
		btn.setPosition(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
		btn.addListener(new ClickListener() {
				@Override
				public void clicked(InputEvent event, float x, float y) {
					if (player.died)
					{
						restart();
					}
				}
			});

		mainMenu.setPosition(btn.getX(), btn.getY() - tt.getHeight()*2 - 5*Info.PIXEL_SIZE);
		mainMenu.addListener(new ClickListener() {
				@Override
				public void clicked(InputEvent event, float x, float y) {
					game.setScreen(game.mainScreen);
					restart();
				}
		});
		stage.addActor(new GameController(stage));
		stage.addActor(btn);
		stage.addActor(mainMenu);
		
	}
	
	private void update() {
		int ss = score;
		int delta = (int)(Math.random()*(30 - (ss*0.01f < 12?ss*0.1f:12)));
		if (timer++ % (delta > 0?delta:1) == 0 && timer >= 200)
		{
			Stone st = stonePool.obtain();
			st.init(score*0.05f + 10, camera.viewportWidth, (float)(Math.random() * Gdx.graphics.getHeight()));
			stones.add(st);
			
			
			//stones.add(new Stone(stones, 2, camera.viewportWidth, (float)(Math.random()*camera.viewportHeight)));
		} 
		
		if (timer < 5){
			for (int i = 0;i < 100;++i) {
				Star sta = starPool.obtain();
				sta.init((int)(Math.random() * Gdx.graphics.getWidth()), (int)(Math.random() * Gdx.graphics.getHeight()), score*0.0005f + 0.1f);
				stars.add(sta);
			}
		}
		
		if (timer % ((int)(Math.random() * 40)+1) == 0) {
			Star star = starPool.obtain();
			star.init(Gdx.graphics.getWidth(), (int)(Math.random() * Gdx.graphics.getHeight()), score*0.0005f + 0.15f);
			stars.add(star);
		}
		
		if (timer % 15 == 0 && scoreCounting && !player.died) {
			score++;
		}

		if (timer <= 20) {
			player.velocity.x = 10;
		} else {
			player.velocity.x = 0;
		}

		if (!player.died)
		{
			if (player.position.y < 0) {
				player.position.y = 0;
			}

			if (player.position.y + player.box.getHeight() > Gdx.graphics.getHeight()) {
				player.position.y = Gdx.graphics.getHeight() - player.box.getHeight();
			}
		}
		if (player.died) {
			btn.setVisible(true);
			mainMenu.setVisible(true);
		} else {
			btn.setVisible(false);
			mainMenu.setVisible(false);
		}
		
	}

	@Override
	public void render(float delta) {
		update();
		Gdx.gl.glClearColor(0.1f, 0.1f, 0.5f, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

		batch.begin();
		if (!player.died)
		{
			for (Star s:stars) {
				s.draw(batch);
			}
			
			player.draw(batch);
			
			for (Stone stone : stones)
			{
				stone.draw(batch);
				stone.isHitPlayer(player);
			}
			
		}
		else font.draw(batch, "GAMEOVER", 0, camera.viewportHeight / 3);
		font.draw(batch, "Score:"+score, 0, camera.viewportHeight);
		if (usageOpen) {
			usage.draw(batch);
		}
		batch.end();
		
		stage.act();
		stage.draw();
		
		
		camera.update();

		Stone st;
		int len = stones.size;
		for (int i = len;--i >= 0;)
		{
			st = stones.get(i);
			if (st.removeAble)
			{
				if (!player.died) scoreCounting = true;
				stones.removeIndex(i);
				stonePool.free(st);
			}
		}
		
		Star sta;
		int leng = stars.size;
		for (int i = leng;--i >= 0;)
		{
			sta = stars.get(i);
			if (sta.x < 0)
			{
				//if (!player.died) ++score;
				stars.removeIndex(i);
				starPool.free(sta);
			}
		}
	}

	@Override
	public void hide() {
		// TODO: Implement this method
		super.hide();
		stage.dispose();
		batch.dispose();
		batch2.dispose();
		font.dispose();
		restart();
	}

	public void restart() {
		player.died = false;
		timer = 0;
		stones.clear();
		stars.clear();
		score = 0;
		player.position.x = -20;
		scoreCounting = false;
	}

	class GameController extends Actor {
		InputListener inputListener = new InputListener() {

			@Override
			public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
				// TODO: Implement this method
				if (player.died)
				{
					restart();
				}
				return false;
			}
		};
		
		DragListener dragListener = new DragListener() {
			Vector2 point = new Vector2();
			Vector2 lastPosition;
			@Override
			public void dragStart(InputEvent event, float x, float y, int pointer) {
				super.dragStart(event, x, y, pointer);
				usageOpen = false;
				point.set(x, y);
				lastPosition = player.position.cpy();
			}
			
			@Override
			public void drag(InputEvent event, float x, float y, int pointer) {
				// TODO: Implement this method
				super.drag(event, x, y, pointer);
				if (!player.died) {
					player.position.y = lastPosition.y - (point.y - y);
				}
			}
		};
		
		public GameController(Stage stage) {
			addListener(dragListener);
			setSize(stage.getCamera().viewportWidth, stage.getCamera().viewportHeight);
		}

		@Override
		public void draw(Batch batch, float parentAlpha) {
			// TODO: Implement this method
			super.draw(batch, parentAlpha);
			
			
		}
	}
}
